package com.road.vast.springboot.realm;

import com.road.vast.springboot.project.pojo.PeUser;
import com.road.vast.springboot.project.service.PeUserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.relational.core.sql.UpdateBuilder;

import java.util.Map;
import java.util.Set;

/**
 * @Author 郭泽鹏
 * @Date 2020/8/1 23:03
 * @Version 1.0
 * @Description 自定义realm域：用户登录时的自定义认证和授权方法
 */
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    PeUserService userService;

    /**
     * 设置realm域名称
     * @param name realm域名称
     */
    @Override
    public void setName(String name) {
        super.setName("CustomRealm");
    }

    /**
     * 授权方法
     *      操作的时候，判断用户是否具有相应的权限
     *          先认证 -- 安全数据
     *          再授权 -- 根据安全数据获取用户具有的所有操作权限
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("*******执行了授权方法");

        //1.获取已认证的用户数据
        PeUser user = (PeUser) principalCollection.getPrimaryPrincipal();   //得到唯一的安全数据

        //2.根据用户数据获取用户的权限信息
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Map<String, Object> map = userService.getRolesAndPermissionByUserId(user.getId());
        Set<String> roleNames = (Set<String>) map.get("roleNames");
        Set<String> permCodes = (Set<String>) map.get("permCodes");
        info.setStringPermissions(permCodes);
        info.setRoles(roleNames);
        return info;
    }

    /**
     * 认证方法
     * @param authenticationToken 封装传递的用户名和密码
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("*******执行了认证方法");
        //1.获取登录的用户名和密码
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        String password = new String(token.getPassword());
        System.out.println("*******密码为：" + password);
        //2.根据用户名查询数据库
        PeUser user = userService.findByName(username);
        //3.判断用户是否存在或者密码是否一致
        if (user != null && user.getPassword().equals(password)){
            //4.如果一致返回安全数据
            //参数：安全数据，密码，realm域名
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
            return info;
        }
        //5.不一致，返回null（抛出异常）
        return null;
    }
}
